home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 28
/
Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso
/
Aminet
/
dev
/
lang
/
fpcsrc.lha
/
fpc
/
compiler
/
cgi386ad.inc
< prev
next >
Wrap
Text File
|
1998-09-24
|
58KB
|
1,287 lines
{
$Id: cgi386ad.inc,v 1.2.2.1 1998/04/08 11:38:43 peter Exp $
Copyright (c) 1993-98 by Florian Klaempfl
This include file generates i386+ assembler from the parse tree
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
procedure secondas(var p : ptree);
var
pushed : tpushed;
begin
secondpass(p^.left);
{ save all used registers }
pushusedregisters(pushed,$ff);
{ push instance to check: }
case p^.left^.location.loc of
LOC_REGISTER,LOC_CREGISTER:
exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
S_L,p^.left^.location.register)));
LOC_MEM,LOC_REFERENCE:
exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
S_L,newreference(p^.left^.location.reference))));
else internalerror(100);
end;
{ we doesn't modifiy the left side, we check only the type }
set_location(p^.location,p^.left^.location);
{ generate type checking }
secondpass(p^.right);
case p^.right^.location.loc of
LOC_REGISTER,LOC_CREGISTER:
begin
exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
S_L,p^.right^.location.register)));
ungetregister32(p^.right^.location.register);
end;
LOC_MEM,LOC_REFERENCE:
begin
exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
S_L,newreference(p^.right^.location.reference))));
del_reference(p^.right^.location.reference);
end;
else internalerror(100);
end;
emitcall('DO_AS',true);
{ restore register, this restores automatically the }
{ result }
popusedregisters(pushed);
end;
procedure secondloadvmt(var p : ptree);
begin
p^.location.register:=getregister32;
exprasmlist^.concat(new(pai386,op_csymbol_reg(A_MOV,
S_L,newcsymbol(pobjectdef(pclassrefdef(p^.resulttype)^.definition)^.vmt_mangledname,0),
p^.location.register)));
end;
procedure secondis(var p : ptree);
var
pushed : tpushed;
begin
{ save all used registers }
pushusedregisters(pushed,$ff);
secondpass(p^.left);
p^.location.loc:=LOC_FLAGS;
p^.location.resflags:=F_NE;
{ push instance to check: }
case p^.left^.location.loc of
LOC_REGISTER,LOC_CREGISTER:
begin
exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
S_L,p^.left^.location.register)));
ungetregister32(p^.left^.location.register);
end;
LOC_MEM,LOC_REFERENCE:
begin
exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
S_L,newreference(p^.left^.location.reference))));
del_reference(p^.left^.location.reference);
end;
else internalerror(100);
end;
{ generate type checking }
secondpass(p^.right);
case p^.right^.location.loc of
LOC_REGISTER,LOC_CREGISTER:
begin
exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
S_L,p^.right^.location.register)));
ungetregister32(p^.right^.location.register);
end;
LOC_MEM,LOC_REFERENCE:
begin
exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
S_L,newreference(p^.right^.location.reference))));
del_reference(p^.right^.location.reference);
end;
else internalerror(100);
end;
emitcall('DO_IS',true);
exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_B,R_AL,R_AL)));
popusedregisters(pushed);
end;
procedure setaddresult(cmpop,unsigned : boolean;var p :ptree);
var
flags : tresflags;
begin
if (p^.left^.resulttype^.deftype<>stringdef) and
not ((p^.left^.resulttype^.deftype=setdef) and
(psetdef(p^.left^.resulttype)^.settype<>smallset)) then
begin
{ this can be useful if for instance length(string) is called }
if (p^.left^.location.loc=LOC_REFERENCE) or
(p^.left^.location.loc=LOC_MEM) then
ungetiftemp(p^.left^.location.reference);
if (p^.right^.location.loc=LOC_REFERENCE) or
(p^.right^.location.loc=LOC_MEM) then
ungetiftemp(p^.right^.location.reference);
end;
{ in case of comparison operation the put result in the flags }
if cmpop then
begin
if not(unsigned) then
begin
if p^.swaped then
case p^.treetype of
equaln : flags:=F_E;
unequaln : flags:=F_NE;
ltn : flags:=F_G;
lten : flags:=F_GE;
gtn : flags:=F_L;
gten : flags:=F_LE;
end
else
case p^.treetype of
equaln : flags:=F_E;
unequaln : flags:=F_NE;
ltn : flags:=F_L;
lten : flags:=F_LE;
gtn : flags:=F_G;
gten : flags:=F_GE;
end;
end
else
begin
if p^.swaped then
case p^.treetype of
equaln : flags:=F_E;
unequaln : flags:=F_NE;
ltn : flags:=F_A;
lten : flags:=F_AE;
gtn : flags:=F_B;
gten : flags:=F_BE;
end
else
case p^.treetype of
equaln : flags:=F_E;
unequaln : flags:=F_NE;
ltn : flags:=F_B;
lten : flags:=F_BE;
gtn : flags:=F_A;
gten : flags:=F_AE;
end;
end;
p^.location.loc:=LOC_FLAGS;
p^.location.resflags:=flags;
end;
end;
procedure secondaddstring(var p : ptree);
var
swapp : ptree;
pushedregs : tpushed;
href : treference;
pushed,cmpop : boolean;
begin
{ string operations are not commutative }
if p^.swaped then
begin
swapp:=p^.left;
p^.left:=p^.right;
p^.right:=swapp;
{ because of jump being produced at comparison below: }
p^.swaped:=not(p^.swaped);
end;
case p^.treetype of
addn :
begin
cmpop:=false;
secondpass(p^.left);
if (p^.left^.treetype<>addn) then
begin
{ can only reference be }
{ string in register would be funny }
{ therefore produce a temporary string }
{ release the registers }
del_refere